home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1985-1992 New York University
- *
- * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
- * warranty (none) and distribution info and also the GNU General Public
- * License for more details.
-
- */
- /* continuation of interpreter procedures - part c */
-
- /* include standard header files */
- #include <stdlib.h>
- #include "config.h"
- #include "int.h"
- #include "ivars.h"
- #include "machineprots.h"
- #include "farithprots.h"
- #include "intaprots.h"
- #include "intbprots.h"
- #include "intcprots.h"
-
- static int get_variable_bound(int *, int []);
-
- void rselect(int field) /*;rselect*/
- {
- /*
- * Perform the Ada record selection operation:
- *
- * Get the address of the record type template from the TOS
- * Get the address of the record object from the TOS
- * Get the number of the component(or field) from the instruction
- * stream
- *
- * Check the existence of that particular component in that particular
- * record(and raise CONSTRAINT_ERROR otherwise)
- *
- * Push the absolute address of the component on TOS. If component
- * is an array, push also the address of the array type template.
- * If the type of this array depends on a discriminant of the record
- * a template must be dynamically built.
- */
-
- int
- type_base, type_off, record_base, record_off, field_offset,
- *type_ptr, *record_ptr, *field_table_ptr, *case_table_ptr,
- *case_ptr, type_type, next_case, discr_number, discr_offset,
- first_field, last_field, value_discr, val_high, nb_choices,
- nb_field, nb_fixed, *field_ptr, *component_ptr, *a_type_ptr,
- *u_type_ptr, nb_dim, low, high, comp_off, comp_base, component_size,
- object_size, template_size, *new_type_ptr, *some_ptr;
-
- POP_ADDR(type_base, type_off);
- POP_ADDR(record_base, record_off);
- type_ptr = ADDR(type_base, type_off);
- record_ptr = ADDR(record_base, record_off);
- type_type = TYPE(type_ptr);
-
- /* constrained record subtype */
-
- if (type_type == TT_C_RECORD) { /* find base type */
- type_base = C_RECORD(type_ptr)->cbase;
- type_off = C_RECORD(type_ptr)->coff;
- type_ptr = ADDR(type_base, type_off);
- type_type = TYPE(type_ptr);
- }
- else if (type_type == TT_D_RECORD) {
- type_base = D_TYPE(type_ptr)->dbase;
- type_off = D_TYPE(type_ptr)->doff;
- type_ptr = ADDR(type_base, type_off);
- type_type = TYPE(type_ptr);
- }
- else if (type_type == TT_RECORD) {
- field_table_ptr = type_ptr + WORDS_RECORD;
- nb_fixed = RECORD(type_ptr)->nb_field;
- }
-
- if (type_type == TT_U_RECORD || type_type == TT_V_RECORD) {
- nb_fixed = U_RECORD(type_ptr)->nb_fixed_u;
- nb_field = U_RECORD(type_ptr)->nb_field_u;
- field_table_ptr = type_ptr + WORDS_U_RECORD;
- case_table_ptr = field_table_ptr + 3 * nb_field;
- }
-
- /* The result is simple to obtain... unless the record has varying size */
-
- if (type_type == TT_V_RECORD) {
- field_offset = 0;
- first_field = 0;
- last_field = nb_fixed - 1;
- next_case = U_RECORD(type_ptr)->first_case;
- nb_discr = U_RECORD(type_ptr)->nb_discr_u;
-
- for (i = 0; i < nb_discr; i++)
- discr_list[i] = *(record_ptr + i);
-
- for (;;) {
- field_ptr = 3 * first_field + field_table_ptr;
- for (i = first_field; i <= MIN((field - 1), last_field); i++) {
- /* accumulate size of components */
- component_ptr = ADDR(*(field_ptr + 1), *(field_ptr + 2));
- field_offset += actual_size(component_ptr, discr_list);
- field_ptr += 3;
- }
-
- if (field >= first_field && field <= last_field) {
- break;
- }
- else if (field < first_field
- ||(field > last_field && next_case == -1)) {
-
- raise(CONSTRAINT_ERROR, "Record component not present");
- return;
- }
-
- /* We have : field > last_field and next_case /= -1 */
-
- case_ptr = case_table_ptr + next_case;
- discr_number = *case_ptr++;
- discr_offset = *(field_table_ptr + 3 * discr_number);
- value_discr = *(record_ptr + discr_offset);
- nb_choices = *case_ptr;
- case_ptr += 4;
- val_high = *case_ptr;
- for (i = 2; i <= nb_choices; i++) {
- if (val_high > value_discr)
- break;
- case_ptr += 4;
- val_high = *case_ptr;
- }
- next_case = *--case_ptr;
- last_field = *--case_ptr;
- first_field = *--case_ptr;
- }
- field_ptr = field_table_ptr + 3 * field;
- }
-
- /* Record is not varying */
-
- else {
- field_ptr = field_table_ptr + 3 * field;
- field_offset = *field_ptr;
- }
-
- PUSH_ADDR(record_base, field_offset + record_off);
-
- /* check if component is an array */
-
- type_base = *(field_ptr + 1);
- type_off = *(field_ptr + 2);
- type_type = TYPE(ADDR(type_base, type_off));
-
- if ( type_type == TT_S_ARRAY
- || type_type == TT_U_ARRAY
- || type_type == TT_C_ARRAY
- || type_type == TT_D_ARRAY) {
-
- if (type_type == TT_D_ARRAY) {
- /* must build a type template */
- /* necessarily the record is a TT_V_RECORD or a TT_U_RECORD with */
- /* default values for the discriminants */
- nb_discr = U_RECORD(type_ptr)->nb_discr_u;
- for (i = 0; i < nb_discr; i++)
- discr_list[i] = *(record_ptr + i);
- a_type_ptr = ADDR(type_base, type_off);
- nb_dim = D_TYPE(a_type_ptr)->nb_discr_d;
- type_base = D_TYPE(a_type_ptr)->dbase;
- type_off = D_TYPE(a_type_ptr)->doff;
- u_type_ptr = ADDR(type_base, type_off);
- a_type_ptr += WORDS_D_TYPE;/* =bounds */
- type_type = *u_type_ptr;
-
- if (nb_dim == 1) {
- /* unidimensional case: we build an s_array */
- low = get_variable_bound(a_type_ptr, discr_list);
- a_type_ptr += 2;
- high = get_variable_bound(a_type_ptr, discr_list);
- if (type_type == TT_S_ARRAY) {
- component_size = S_ARRAY(u_type_ptr)->component_size;
- }
- else {
- comp_base = ARRAY(u_type_ptr)->component_base;
- comp_off = ARRAY(u_type_ptr)->component_offset;
- component_size = SIZE(ADDR(comp_base, comp_off));
- }
- object_size = component_size *(high - low + 1);
- if (object_size < 0)
- object_size = 0;
-
- create(WORDS_S_ARRAY, &type_base, &type_off, &new_type_ptr);
- S_ARRAY(new_type_ptr)->ttype = TT_S_ARRAY;
- S_ARRAY(new_type_ptr)->object_size = object_size;
- S_ARRAY(new_type_ptr)->component_size = component_size;
- S_ARRAY(new_type_ptr)->index_size = 1;
- S_ARRAY(new_type_ptr)->salow = low;
- S_ARRAY(new_type_ptr)->sahigh = high;
- }
-
- else { /* nb_dim > 1 */
- template_size = 2 *(nb_dim - 1) + WORDS_ARRAY;
- create(template_size, &type_base, &type_off, &new_type_ptr);
- ARRAY(new_type_ptr)->ttype = TT_C_ARRAY;
- ARRAY(new_type_ptr)->dim = nb_dim;
- comp_base = ARRAY(u_type_ptr)->component_base;
- comp_off = ARRAY(u_type_ptr)->component_offset;
- ARRAY(new_type_ptr)->component_base = comp_base;
- ARRAY(new_type_ptr)->component_offset = comp_off;
- component_size = SIZE(ADDR(comp_base, comp_off));
- /* Beware: indices in reverse order */
- some_ptr = new_type_ptr + WORDS_ARRAY + 2 * nb_dim - 3;
- for (i = 1; i <= nb_dim; i++) {
- low = get_variable_bound(a_type_ptr, discr_list);
- a_type_ptr += 2;
- high = get_variable_bound(a_type_ptr, discr_list);
- a_type_ptr += 2;
- create(WORDS_I_RANGE, &bas2, &off2, &ptr2);
- TYPE(ptr2) = TT_I_RANGE;
- SIZE(ptr2) = 1;
- I_RANGE(ptr2)->ilow = low;
- I_RANGE(ptr2)->ihigh = high;
- *some_ptr-- = off2;
- *some_ptr-- = bas2;
- if (high >= low)
- component_size *= (high - low + 1);
- else
- component_size = 0;
- }
- SIZE(new_type_ptr) = component_size;
- }
- }
- PUSH_ADDR(type_base, type_off);
- }
-
- /* no check to perform if done already for varying size records */
-
- if (type_type == TT_V_RECORD)
- return;
-
- first_field = 0;
- last_field = nb_fixed - 1;
- next_case = U_RECORD(type_ptr)->first_case;
-
- for (;;) {
- if ((field >= first_field) &&(field <= last_field)) {
- return;
- }
- else if (field < first_field
- ||(field > last_field && next_case == -1)) {
- raise(CONSTRAINT_ERROR, "Record component not present");
- return;
- }
-
- /* then we have : field > last_field and next_case /= -1 */
-
- case_ptr = case_table_ptr + next_case;
- discr_number = *case_ptr++;
- discr_offset = *(field_table_ptr + 3 * discr_number);
- value_discr = *(record_ptr + discr_offset);
- nb_choices = *case_ptr;
- case_ptr += 4;
- val_high = *case_ptr;
- for (i = 2; i <= nb_choices; i++) {
- if (val_high > value_discr) {
- break;
- }
- case_ptr += 4;
- val_high = *case_ptr;
- }
- next_case = *--case_ptr;
- last_field = *--case_ptr;
- first_field = *--case_ptr;
- }
-
- }
-
- static int get_variable_bound(int *bound_ptr, int discr_list[])
- /*;get_variable_bound*/
- {
- int bound = *(bound_ptr + 1);
- if (*bound_ptr == 1)
- bound = discr_list[bound];
- return bound;
- }
-
- int actual_size(int *type_ptr, int discr_list[]) /*;actual_size*/
- {
- /*
- * Returns the actual size of an object of the type designated by
- * type_ptr, with the discriminants of the enclosing record
- * given by discr_list
- *
- * the real problem arises with discriminant dependant types and
- * varying length records(or their subtypes)
- */
-
- int new_discr_list[MAX_DISCR];
- int *base_type_ptr, *discr_ptr, nb_discr, i, size, *component_ptr;
- int nb_dim, low, high;
- int nb_field, nb_fixed, *field_ptr, *case_table_ptr, *field_table_ptr;
- int first_field, last_field, next_case, *case_ptr;
- int discr_number, value_discr, nb_choices;
-
- if (TYPE(type_ptr) == TT_D_RECORD) {
- base_type_ptr = ADDR(D_TYPE(type_ptr)->dbase, D_TYPE(type_ptr)->doff);
- discr_ptr = type_ptr + WORDS_D_TYPE;
- nb_discr = D_TYPE(type_ptr)->nb_discr_d;
- for (i = 0; i < nb_discr; i++) {
- new_discr_list[i] = get_variable_bound(discr_ptr, discr_list);
- #ifdef TBSN
- *discr_ptr++ = 0; /* To be checked: patch the template */
- *discr_ptr++ = new_discr_list[i];
- #endif
- discr_ptr += 2;
- }
- size = actual_size(base_type_ptr, new_discr_list);
- SIZE(type_ptr) = size;
- }
-
- else if (TYPE(type_ptr) == TT_D_ARRAY) {
- base_type_ptr = ADDR(D_TYPE(type_ptr)->dbase, D_TYPE(type_ptr)->doff);
- discr_ptr = type_ptr + WORDS_D_TYPE;
- nb_dim = D_TYPE(type_ptr)->nb_discr_d;
-
- if ( TYPE(base_type_ptr) == TT_U_ARRAY
- || TYPE(base_type_ptr) == TT_C_ARRAY) {
- component_ptr =
- ADDR(ARRAY(base_type_ptr)->component_base,
- ARRAY(base_type_ptr)->component_offset);
- #ifdef TBSL
- -- note review use of NULL corresponding to setl [] ds 9-30-85
- #endif
- size = actual_size(component_ptr, NULL_INT);
- }
- else if (TYPE(base_type_ptr) == TT_S_ARRAY) {
- size = S_ARRAY(base_type_ptr)->component_size;
- }
-
- for (i = 1; i <= nb_dim; i++) {
- low = get_variable_bound(discr_ptr, discr_list);
- #ifdef TBSN
- *discr_ptr++ = 0; /* to be checked: patch the template */
- *discr_ptr++ = low;
- #endif
- discr_ptr += 2;
- high = get_variable_bound(discr_ptr, discr_list);
- #ifdef TBSN
- *discr_ptr++ = 0; /* to be checked: patch the template */
- *discr_ptr++ = high;
- #endif
- discr_ptr += 2;
- size = size *(MAX(0, high - low + 1));
- }
- SIZE(type_ptr) = size;
- }
- else if (TYPE(type_ptr) == TT_C_RECORD) {
- if ((size = SIZE(type_ptr)) < 0) {
- base_type_ptr = ADDR(C_RECORD(type_ptr)->cbase,
- C_RECORD(type_ptr)->coff);
- nb_discr = C_RECORD(type_ptr)->nb_discr_c;
- for (i = 0; i < nb_discr; i++)
- new_discr_list[i] = *(type_ptr + WORDS_C_RECORD + i);
- size = actual_size(base_type_ptr, new_discr_list);
- }
- }
-
- else if (TYPE(type_ptr) == TT_V_RECORD) {
- nb_field = U_RECORD(type_ptr)->nb_field_u;
- nb_fixed = U_RECORD(type_ptr)->nb_fixed_u;
- field_table_ptr = type_ptr + WORDS_U_RECORD;
- case_table_ptr = field_table_ptr + 3 * nb_field;
- size = 0;
- first_field = 0;
- last_field = nb_fixed - 1;
- next_case = U_RECORD(type_ptr)->first_case;
- for (;;) {
- field_ptr = 3 * first_field + field_table_ptr;
- for (i = first_field; i <= last_field; i++) {
- /* accumulate size of components */
- component_ptr = ADDR(*(field_ptr + 1), *(field_ptr + 2));
- size += actual_size(component_ptr, discr_list);
- field_ptr += 3;
- }
-
- if (next_case == -1)
- break;
-
- /* we have : next_case != -1 */
-
- case_ptr = case_table_ptr + next_case;
- discr_number = *case_ptr++;
- value_discr = discr_list[discr_number];
- nb_choices = *case_ptr;
- case_ptr += 4;
- val_high = *case_ptr;
- for (i = 2; i <= nb_choices; i++) {
- if (val_high > value_discr)
- break;
- case_ptr += 4;
- val_high = *case_ptr;
- }
- next_case = *--case_ptr;
- last_field = *--case_ptr;
- first_field = *--case_ptr;
- }
- }
-
- else
- size = SIZE(type_ptr);
-
- return size;
- }
-
- void record_move(int *ptr_a, int *ptr_v, int *ptr_t) /*;record_move*/
- {
- int discr;
-
- length1 = SIZE(ptr_t);
-
- switch(TYPE(ptr_t)) {
-
- case TT_RECORD:
- break;
-
- case TT_D_RECORD:
- nb_discr = D_TYPE(ptr_t)->nb_discr_d;
- ptr_a++; /* skip constrained flag */
- ptr_v++;
- length1 -= nb_discr--;
- i = nb_discr;
- while (i-- > 0) {
- if (*ptr_a++ != *ptr_v++) {
- raise(CONSTRAINT_ERROR, "Discriminant");
- return;
- }
- }
- break;
-
- case TT_C_RECORD:
- case TT_U_RECORD:
-
- /* the type given must not be trusted, as this may be an assignment
- * to some unconstrained out or in out parameter, in which case the
- * status constrained is inherited from the actual
- */
-
- if (*ptr_a == 0) { /* unconstrained */
-
- length1--; /* constrained flag is not copied ! */
- ptr_a++;
- ptr_v++;
- for (i = 0; i < length1; i++)
- *ptr_a++ = *ptr_v++;
- return;
- }
- else {
- if (TYPE(ptr_t) == TT_C_RECORD)
- nb_discr = C_RECORD(ptr_t)->nb_discr_c;
- else
- nb_discr = U_RECORD(ptr_t)->nb_discr_u;
- ptr_a++; /* skip contrained flag */
- ptr_v++;
- length1 -= nb_discr--;
- i = nb_discr;
- while(i-- > 0) {
- if (*ptr_a++ != *ptr_v++) {
- raise(CONSTRAINT_ERROR, "Discriminant");
- return;
- }
- }
- }
- break;
-
- case TT_V_RECORD:
- if (*ptr_a == 0) { /* unconstrained */
- /* constrained flag is not copied ! */
- length1--;
- ptr_a++;
- ptr_v++;
- if (TYPE(ptr_t) == TT_C_RECORD)
- nb_discr = C_RECORD(ptr_t)->nb_discr_c;
- else
- nb_discr = U_RECORD(ptr_t)->nb_discr_u;
- discr_list[0] = *ptr_a;
- for (i = 1; i < nb_discr; i++) {
- /*
- discr = *ptr_a++;
- discr_list[i] = discr;
- if (discr != *ptr_v++)
- raise(CONSTRAINT_ERROR, "Discriminant");
- return;
- */
- discr_list [i] = *ptr_v;
- *ptr_a++ = *ptr_v++;
- }
- length1 = actual_size(ptr_t, discr_list) - nb_discr;
- for (i = 0; i < length1; i++)
- *ptr_a++ = *ptr_v++;
- return;
- }
- else {
- if (TYPE(ptr_t) == TT_C_RECORD)
- nb_discr = C_RECORD(ptr_t)->nb_discr_c;
- else
- nb_discr = U_RECORD(ptr_t)->nb_discr_u;
- discr_list[0] = *ptr_a;
- ptr_a++; /* skip constrained flag */
- ptr_v++;
- for (i = 1; i < nb_discr; i++) {
- discr = *ptr_a++;
- discr_list[i] = discr;
- if (discr != *ptr_v++) {
- raise(CONSTRAINT_ERROR, "Discriminant");
- return;
- }
- }
- length1 = actual_size(ptr_t, discr_list) - nb_discr;
- }
- break;
- }
-
- for (i = 0; i < length1; i++)
- *ptr_a++ = *ptr_v++;
- }
-
- void membership() /*;membership*/
- {
- int some_bool;
-
- POP_ADDR(bse, off);
-
- switch(TYPE(ADDR(bse, off))) {
-
- case TT_I_RANGE:
- case TT_E_RANGE:
- case TT_ENUM:
- POP(value);
- PUSH((I_RANGE(ADDR(bse, off))->ilow <=
- I_RANGE(ADDR(bse,off))->ihigh) &&
- (value >= I_RANGE(ADDR(bse, off))->ilow &&
- value <= I_RANGE(ADDR(bse, off))->ihigh));
- break;
-
- case TT_FL_RANGE:
- POPF(rvalue);
- PUSH((FL_RANGE(ADDR(bse, off))->fllow <=
- FL_RANGE(ADDR(bse,off))->flhigh) &&
- (rvalue >= FL_RANGE(ADDR(bse, off))->fllow &&
- rvalue <= FL_RANGE(ADDR(bse, off))->flhigh));
- break;
-
- case TT_FX_RANGE:
- POPL(lvalue);
- PUSH((FX_RANGE(ADDR(bse, off))->fxlow <=
- FX_RANGE(ADDR(bse,off))->fxhigh) &&
- (lvalue >= FX_RANGE(ADDR(bse, off))->fxlow &&
- lvalue <= FX_RANGE(ADDR(bse, off))->fxhigh));
- break;
-
- case TT_C_RECORD:
- ptr1 = ADDR(bse, off);
- POP_ADDR(bse, off);
- ptr2 = ADDR(bse, off);
- nb_discr = C_RECORD(ptr1)->nb_discr_c;
- some_bool = TRUE;
- ptr1 += WORDS_C_RECORD;
- for (i = 1; i < nb_discr; i++)
- if (*++ptr2 != *++ptr1) {
- some_bool = FALSE;
- }
- PUSH(some_bool);
- break;
-
- case TT_V_RECORD:
- case TT_U_RECORD:
- POP_ADDR(bse, off);
- PUSH(TRUE);
- break;
-
- /* If the array type is unconstrained, the value must be within the
- * given bounds. If constrained bounds must be the same. This rule is
- * the same for null arrays.
- */
- case TT_U_ARRAY:
- ptr1 = ADDR(bse, off);
- POP_ADDR(bse, off);
- ptr3 = ADDR(bse, off);/* type of the value */
- POP_ADDR(bse, off);/* to get rid of the value */
- /* PUSH(qual_index(ptr1, ptr3)); */
- PUSH(qual_sub(ptr1, ptr3));
- break;
-
- case TT_C_ARRAY:
- case TT_S_ARRAY:
- ptr1 = ADDR(bse, off);
- POP_ADDR(bse, off);
- ptr3 = ADDR(bse, off);/* type of the value */
- POP_ADDR(bse, off);/* to get rid of the value */
- PUSH(qual_index(ptr1, ptr3));
- break;
-
- case TT_ACCESS:
- /* membership on an access type is converted into a test on the
- * designated type. If the designated type itself is an access,
- * no further checks are needed.
- */
- POP_ADDR(bse, off);
- PUSH(TRUE);
- break;
-
- case TT_TASK:
- /* Does nothing need to be checked? This case added because
- * default popped too many elements off stack - failed c45291a.
- * bp - 07/04/91.
- */
- POP(value);
- PUSH(TRUE);
- break;
-
- default:
- POP_ADDR(bse, off);
- PUSH(TRUE);
- break;
- }
- }
-
- int qual_index(int *type_ptr1, int *type_ptr2) /*;qual_index*/
- {
-
- if (TYPE(type_ptr1) == TT_U_ARRAY || TYPE(type_ptr1) == TT_C_ARRAY) {
- if (TYPE(type_ptr2) == TT_U_ARRAY || TYPE(type_ptr2) == TT_C_ARRAY) {
- nb_dim = ARRAY(type_ptr1)->dim;
- type_ptr1 = &(ARRAY(type_ptr1)->index1_base);
- type_ptr2 = &(ARRAY(type_ptr2)->index1_base);
- for (i = 1; i <= nb_dim; i++) {
- bas1 = *type_ptr1++;
- off1 = *type_ptr1++;
- ptr1 = ADDR(bas1, off1);
- bas2 = *type_ptr2++;
- off2 = *type_ptr2++;
- ptr2 = ADDR(bas2, off2);
- if (I_RANGE(ptr1)->ilow != I_RANGE(ptr2)->ilow ||
- I_RANGE(ptr1)->ihigh != I_RANGE(ptr2)->ihigh)
- return FALSE;
- }
- }
-
- else if (TYPE(type_ptr2) == TT_S_ARRAY)
- return qual_index(type_ptr2, type_ptr1);
-
- else if (TYPE(type_ptr2) == TT_D_ARRAY) {
- raise(SYSTEM_ERROR, "qual index on TT_D_ARRAY");
- return FALSE;
- #ifdef TBSN
- return qual_index(type_ptr2, type_ptr1);
- #endif
- }
- }
-
- else if (TYPE(type_ptr1) == TT_S_ARRAY) {
- if (TYPE(type_ptr2) == TT_U_ARRAY || TYPE(type_ptr2) == TT_C_ARRAY) {
- bas2 = ARRAY(type_ptr2)->index1_base;
- off2 = ARRAY(type_ptr2)->index1_offset;
- ptr2 = ADDR(bas2, off2);
- if ( S_ARRAY(type_ptr1)->salow != I_RANGE(ptr2)->ilow
- || S_ARRAY(type_ptr1)->sahigh != I_RANGE(ptr2)->ihigh) {
- return FALSE;
- }
- }
-
- else if (TYPE(type_ptr2) == TT_S_ARRAY) {
- if ( S_ARRAY(type_ptr1)->salow != S_ARRAY(type_ptr2)->salow
- || S_ARRAY(type_ptr1)->sahigh != S_ARRAY(type_ptr2)->sahigh) {
- return FALSE;
- }
- }
-
- else if (TYPE(type_ptr2) == TT_D_ARRAY)
- return qual_index(type_ptr2, type_ptr1);
- }
- else if (TYPE(type_ptr1) == TT_D_ARRAY) {
- raise(SYSTEM_ERROR, "qual index on TT_D_ARRAY");
- return FALSE;
- #ifdef TBSN
- if (TYPE(type_ptr2) == TT_U_ARRAY || TYPE(type_ptr2) == TT_C_ARRAY) {
- nb_dim = ARRAY(type_ptr2)->dim;
- ptr1 = type_ptr1 + WORDS_D_TYPE - 1;
- type_ptr2 = &(ARRAY(type_ptr2)->index1_base);
- for (i = 1; i <= nb_dim; i++) {
- ptr1 += 2;
- bas2 = *type_ptr2++;
- off2 = *type_ptr2++;
- ptr2 = ADDR(bas2, off2);
- if (*ptr1++ != I_RANGE(ptr2)->ilow ||
- *++ptr1 != I_RANGE(ptr2)->ihigh)
- return FALSE;
- }
- }
-
- else if (TYPE(type_ptr2) == TT_S_ARRAY) {
- ptr1 = type_ptr1 + WORDS_D_TYPE + 1;
- if (*ptr1++ != S_ARRAY(type_ptr2)->salow ||
- *++ptr1 != S_ARRAY(type_ptr2)->sahigh) {
- return FALSE;
- }
- }
-
- else if (TYPE(type_ptr2) == TT_D_ARRAY) {
- nb_dim = D_TYPE(type_ptr2)->nb_discr_d;
- ptr1 = type_ptr1 + WORDS_D_TYPE - 1;
- ptr2 = type_ptr2 + WORDS_D_TYPE - 1;
- for (i = 1; i <= nb_dim; i++) {
- ptr1 += 2;
- ptr2 += 2;
- if (*ptr1++ != *ptr2++ || *++ptr1 != *++ptr2)
- return FALSE;
- }
- }
- #endif
- }
- return TRUE;
- }
-
- int qual_sub(int *type_ptr1, int *type_ptr2) /*;qual_sub*/
- {
- switch (TYPE(type_ptr1)) {
-
- case TT_I_RANGE:
- case TT_E_RANGE:
- case TT_ENUM:
- return ((I_RANGE(type_ptr2)->ilow > I_RANGE(type_ptr2)->ihigh)
- || ((I_RANGE(type_ptr2)->ilow >= I_RANGE(type_ptr1)->ilow)
- && (I_RANGE(type_ptr2)->ihigh <= I_RANGE(type_ptr1)->ihigh)));
-
- case TT_FL_RANGE:
- return ((FL_RANGE(type_ptr2)->fllow > FL_RANGE(type_ptr2)->flhigh)
- || ((FL_RANGE(type_ptr2)->fllow >= FL_RANGE(type_ptr1)->fllow)
- && (FL_RANGE(type_ptr2)->flhigh <= FL_RANGE(type_ptr1)->flhigh)));
-
- case TT_FX_RANGE:
- return ((FX_RANGE(type_ptr2)->fxlow > FX_RANGE(type_ptr2)->fxhigh)
- || ((FX_RANGE(type_ptr2)->fxlow >= FX_RANGE(type_ptr1)->fxlow)
- && (FX_RANGE(type_ptr2)->fxhigh <= FX_RANGE(type_ptr1)->fxhigh)));
-
- case TT_U_ARRAY:
- case TT_C_ARRAY:
- if (TYPE(type_ptr2) == TT_U_ARRAY || TYPE(type_ptr2) == TT_C_ARRAY) {
- nb_dim = ARRAY(type_ptr1)->dim;
- type_ptr1 = &(ARRAY(type_ptr1)->index1_base);
- type_ptr2 = &(ARRAY(type_ptr2)->index1_base);
- for (i = 1; i <= nb_dim; i++) {
- bas1 = *type_ptr1++;
- off1 = *type_ptr1++;
- ptr1 = ADDR(bas1, off1);
- bas2 = *type_ptr2++;
- off2 = *type_ptr2++;
- ptr2 = ADDR(bas2, off2);
- if (I_RANGE(ptr2)->ilow > I_RANGE(ptr2)->ihigh) {
- continue;
- }
- else if (I_RANGE(ptr1)->ilow > I_RANGE(ptr2)->ilow ||
- I_RANGE(ptr1)->ihigh < I_RANGE(ptr2)->ihigh) {
- return FALSE;
- }
- }
- return TRUE;
- }
- else if (TYPE(type_ptr2) == TT_S_ARRAY) {
- bas1 = ARRAY(type_ptr1)->index1_base;
- off1 = ARRAY(type_ptr1)->index1_offset;
- ptr1 = ADDR(bas1, off1);
- if (S_ARRAY(type_ptr2)->salow > S_ARRAY(type_ptr2)->sahigh) {
- return TRUE;
- }
- if (S_ARRAY(type_ptr2)->salow < I_RANGE(ptr1)->ilow ||
- S_ARRAY(type_ptr2)->sahigh > I_RANGE(ptr1)->ihigh) {
- return FALSE;
- }
- return TRUE;
- }
- break;
-
- case TT_S_ARRAY:
- if (TYPE(type_ptr2) == TT_U_ARRAY || TYPE(type_ptr2) == TT_C_ARRAY) {
- bas2 = ARRAY(type_ptr2)->index1_base;
- off2 = ARRAY(type_ptr2)->index1_offset;
- ptr2 = ADDR(bas2, off2);
- if (I_RANGE(ptr2)->ilow > I_RANGE(ptr2)->ihigh) {
- return TRUE;
- }
- if ( S_ARRAY(type_ptr1)->salow > I_RANGE(ptr2)->ilow
- || S_ARRAY(type_ptr1)->sahigh < I_RANGE(ptr2)->ihigh){
- return FALSE;
- }
- return TRUE;
- }
- else if (TYPE(type_ptr2) == TT_S_ARRAY) {
- if (S_ARRAY(type_ptr2)->salow > S_ARRAY(type_ptr2)->sahigh) {
- return TRUE;
- }
- if ( S_ARRAY(type_ptr1)->salow > S_ARRAY(type_ptr2)->salow
- || S_ARRAY(type_ptr1)->sahigh < S_ARRAY(type_ptr2)->sahigh) {
- return FALSE;
- }
- return TRUE;
- }
- break;
-
- default:
- ;
- }
- return TRUE;
- }
-
- void qual_discr(int bse, int off) /*;qual_discr*/
- {
- ptr = ADDR(bse, off);
- off = TOS;
- bse = TOSM(1);
- if (TYPE(ptr) == TT_RECORD)
- raise(SYSTEM_ERROR, "Qual discr on simple record");
- else if (TYPE(ptr) == TT_U_RECORD)
- return; /* no constraint applied */
- else if (TYPE(ptr) == TT_C_RECORD) {
- nb_discr = C_RECORD(ptr)->nb_discr_c - 1;
- ptr1 = ADDR(bse, off) + 1;/* skip constrained flag */
- ptr += WORDS_C_RECORD + 1;
- while (nb_discr > 0) {
- if (*ptr++ != *ptr1++) {
- raise(CONSTRAINT_ERROR, "Discriminant");
- return;
- }
- nb_discr--;
- }
- }
- else if (TYPE(ptr) == TT_D_RECORD) {
- raise(SYSTEM_ERROR, "Qual discr on TT_D_RECORD");
- return;
- #ifdef TBSN
- nb_discr = C_RECORD(ptr)->nb_discr_c - 1;
- ptr1 = ADDR(bse, off) + 1;/* skip constrained flag */
- ptr += WORDS_C_RECORD + 3;
- while (nb_discr > 0) {
- if (*ptr++ != *ptr1++) {
- raise(CONSTRAINT_ERROR, "Discriminant");
- return;
- }
- ptr++;
- nb_discr--;
- }
- #endif
- }
- else
- raise(SYSTEM_ERROR, "Unknown record type in qual discr");
- }
-
- void allocate_new() /*;allocate_new*/
- {
-
- POP_ADDR(bse, off); /* addr. of the type template for access type*/
- ptr1 = ADDR(bse, off);
- POP_ADDR(bse, off); /* addr. of the designated type */
- ptr = ADDR(bse, off);
- value = SIZE(ptr);
- if (ACCESS(ptr1)->collection_avail > 0) {
- ACCESS(ptr1)->collection_avail = ACCESS(ptr1)->collection_avail - value;
- }
- else {
- raise(STORAGE_ERROR, "collection exhausted");
- return;
- }
- allocate(value, &bas2, &off2, &ptr2);
-
- switch(*ptr) {
-
- case TT_U_ARRAY:
- case TT_C_ARRAY:
- case TT_S_ARRAY:
- if (bse < heap_base) { /* Non global, must make a copy */
- if (TYPE(ptr) == TT_S_ARRAY) {
- val1 = WORDS_S_ARRAY;
- }
- else {
- nb_dim = ARRAY(ptr)->dim;
- val1 = 2 *(nb_dim - 1) + WORDS_ARRAY;
- }
- allocate(val1, &bse, &off, &ptr1);
- for (i = 0; i < val1; i++)
- *ptr1++ = *ptr++;
- }
-
- /* build an array descriptor */
-
- allocate(4, &bas1, &off1, &ptr1);
- *ptr1++ = bas2;
- *ptr1++ = off2;
- *ptr1++ = bse;
- *ptr1 = off;
- PUSH_ADDR(bas1, off1);
- break;
-
- case TT_C_RECORD:
- PUSH_ADDR(bas2, off2);
- *ptr2 = 1; /* constrained */
- nb_discr = C_RECORD(ptr)->nb_discr_c;
- for (i = 0; i < nb_discr; i++)
- *ptr2++ = *(ptr++ + WORDS_C_RECORD);
- break;
-
- case TT_U_RECORD:
- case TT_V_RECORD:
- raise(SYSTEM_ERROR, "Allocate unconstrained record");
- break;
-
- default:
- PUSH_ADDR(bas2, off2);
- }
- }
-
- void allocate_copy(int bse, int off) /*;allocate_copy*/
- {
- POP_ADDR(bas4, off4); /* addr. of the type template for access type*/
- ptr4 = ADDR(bas4, off4);
- i = TYPE(ADDR(bse, off));
- if (i == TT_U_ARRAY || i == TT_C_ARRAY || i == TT_S_ARRAY)
- POP_ADDR(bse, off);
- value = SIZE(ADDR(bse, off));
- if (ACCESS(ptr4)->collection_avail > 0) {
- ACCESS(ptr4)->collection_avail = ACCESS(ptr4)->collection_avail - value;
- }
- else {
- raise(STORAGE_ERROR, "collection exhausted");
- return;
- }
- allocate(value, &bas1, &off1, &ptr1);
-
- switch(i) {
-
- case TT_U_ARRAY:
- case TT_C_ARRAY:
- case TT_S_ARRAY:
- POP_ADDR(bas2, off2);/* value to be copied */
- ptr2 = ADDR(bas2, off2);
- move_mem(ptr2, ptr1, value);
- bas2 = bas1; /* build an array descriptor */
- off2 = off1;
- allocate(4, &bas1, &off1, &ptr1);
- *ptr1++ = bas2;
- *ptr1++ = off2;
- *ptr1++ = bse;
- *ptr1 = off;
- break;
-
- case TT_RECORD:
- POP_ADDR(bas2, off2);
- ptr2 = ADDR(bas2, off2);
- move_mem(ptr2, ptr1, value);
- break;
-
- case TT_C_RECORD:
- case TT_U_RECORD:
- POP_ADDR(bas2, off2);
- ptr2 = ADDR(bas2, off2);
- move_mem(ptr2, ptr1, value);
- *ptr1 = 1; /* always constrained */
- break;
-
- default: /* scalar, task, or access */
- if (value == 1) {
- POP(val1);
- *ptr1 = val1;
- }
- else if (value == 2) {
- POP(val1);
- *(ptr1 + 1) = val1;
- POP(val1);
- *ptr1 = val1;
- }
- }
- PUSH_ADDR(bas1, off1);
- }
-
- void fix_convert(int *fix_value, struct tt_fx_range *from_template,
- struct tt_fx_range *to_template) /*;fix_convert*/
- {
- /*
- * DESCR: Takes a fixed point number and convert it to another fixed point
- * number.
- * INPUT: value: fixed value to be converted
- * from_template: type template of value
- * to_template: target type template
- * OUTPUT: the converted number
- */
-
- int from_exp_2, to_exp_2;
- int from_exp_5, to_exp_5;
-
- from_exp_5 = from_template->small_exp_5;
- to_exp_5 = to_template->small_exp_5;
-
- from_exp_2 = from_template->small_exp_2;
- to_exp_2 = to_template->small_exp_2;
-
-
- if (from_exp_5 > to_exp_5) {
- pow_of5(mul_fact, from_exp_5 - to_exp_5);
- int_tom(div_fact,1L);
- }
- else {
- int_tom(mul_fact,1L);
- pow_of5(div_fact, to_exp_5 - from_exp_5);
- }
-
- if (from_exp_2 > to_exp_2)
- int_mp2(mul_fact, from_exp_2 - to_exp_2);
- else
- int_mp2(div_fact, to_exp_2 - from_exp_2);
-
- int_mul(fix_value, mul_fact, fix_temp);
- int_div(fix_temp, div_fact, fix_value);
- }
-
- int fix_out_of_bounds(long fvalue, int *itemplate) /*;fix_out_of_bounds*/
- {
- /*
- * DESCR: checks if value is out of the bounds described by template
- * INPUT: value: fixed value to be checked
- * template: pointer to type template.
- * OUTPUT: returns TRUE if out of bounds
- */
-
- return (fvalue > FX_RANGE(itemplate)->fxhigh
- || fvalue < FX_RANGE(itemplate)->fxlow);
- }
-
- void create(int size, int *bse, int *off, int **ptr) /*;create*/
- {
- /* Procedure to allocate a block in memory, heap_next points to the next
- * location and is updated by the call. The parameter size is the number
- * of words to be allocated, ptr points to the newly allocated block,
- * and bse and off are set to the base and offset based on heap_base,ADDR.
- * Procedure create is only used for object creation.
- */
-
- int *p;
-
- if (size < 0 || size >max_mem) {
- raise(SYSTEM_ERROR, "Ridiculous size for object creation");
- *ptr = heap_addr + WORDS_PTR + 1;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- return;
- }
- size += 1 + WORDS_PTR;
- if (heap_next > heap_addr + max_mem - size) {
- if(!allocate_new_heap()) {
- raise(STORAGE_ERROR, "Object creation");
- *ptr = heap_addr + WORDS_PTR + 1;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- return;
- }
- }
-
- #ifdef GARBAGE
- p = BLOCK_FRAME->bf_data_link;
- while (p) {
- if(*--p <= -size) { /* first fit */
- *p = -*p;
- p += WORDS_PTR + 1;
- *ptr = p;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- return;
- }
- p = *(int **)++p;
- }
-
- int *q;
- p = free_list;
- while (p) {
- if(*--p <= -size) { /* first fit */
- *p = -*p;
- p += 1;
- q = *(int **)p;
- *(int **)p = BLOCK_FRAME->bf_data_link;
- BLOCK_FRAME->bf_data_link = free_list;
- free_list = q;
- p += WORDS_PTR;
- *ptr = p;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- return;
- }
- p = *(int **)++p;
- }
- #endif
-
- *heap_next++ = size;
- *(int **)(heap_next) = BLOCK_FRAME->bf_data_link;
- BLOCK_FRAME->bf_data_link = heap_next;
- heap_next += WORDS_PTR;
- *ptr = heap_next;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- heap_next += size - 1 - WORDS_PTR;
- }
-
- void allocate(int size, int *bse, int *off, int **ptr) /*;allocate*/
- {
- /* The ALLOCATE procedure is just like CREATE except that it is used for
- * the case of an allocator allocating from the heap. It differs only
- * in the error message issued if there is insufficient room.
- */
-
- int *p;
-
- if (size < 0) {
- raise(SYSTEM_ERROR, "Ridiculous size for object allocation");
- *ptr = heap_addr + WORDS_PTR + 1;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- return;
- }
- size += 1 + WORDS_PTR;
- if (heap_next > heap_addr + max_mem - size) {
- if(!allocate_new_heap()) {
- raise(STORAGE_ERROR, "Allocator");
- *ptr = heap_addr + WORDS_PTR + 1;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- return;
- }
- }
-
- #ifdef GARBAGE
- p = BLOCK_FRAME->bf_data_link;
- while (p) {
- if(*--p <= -size) { /* first fit */
- *p = -*p;
- p += WORDS_PTR + 1;
- *ptr = p;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- return;
- }
- p = *(int **)++p;
- }
-
- int *q;
- p = free_list;
- while (p) {
- if(*--p <= -size) { /* first fit */
- *p = -*p;
- p += 1;
- q = *(int **)p;
- *(int **)p = BLOCK_FRAME->bf_data_link;
- BLOCK_FRAME->bf_data_link = free_list;
- free_list = q;
- p += WORDS_PTR;
- *ptr = p;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- return;
- }
- p = *(int **)++p;
- }
- #endif
-
- *heap_next++ = size;
- *(int **)(heap_next) = BLOCK_FRAME->bf_data_link;
- BLOCK_FRAME->bf_data_link = heap_next;
- heap_next += WORDS_PTR;
- *ptr = heap_next;
- *off = *ptr - heap_addr;
- *bse = heap_base;
- heap_next += size - 1 - WORDS_PTR;
- }
-
- void push_task_frame(int first) /*;push_task_frame*/
- {
- if (heap_next > heap_addr + max_mem - 4 - 2*WORDS_PTR)
- raise(STORAGE_ERROR, "Tasking");
- else {
- *heap_next++ = 4 + WORDS_PTR;
- *(int **)(heap_next) = BLOCK_FRAME->bf_tasks_declared;
- heap_next += WORDS_PTR;
- BLOCK_FRAME->bf_tasks_declared = heap_next;
- *heap_next++ = first;
- }
- }
-
- int pop_task_frame() /*;pop_task_frame*/
- {
- ptr = BLOCK_FRAME->bf_tasks_declared;
- value = *ptr; /* Task chain */
- BLOCK_FRAME->bf_tasks_declared = *(int **)(ptr - WORDS_PTR);
- *(ptr - WORDS_PTR - 1) = -(*(ptr - WORDS_PTR - 1));/*Release task frame*/
- *(int **)(ptr - WORDS_PTR) = (int *)0;
- return (value);
- }
-
- void deallocate(int *p) /*;deallocate*/
- {
- /* Procedure to deallocate a * block. This is done simply by setting
- * the length word negative, which indicates a block which is not in use.
- */
-
- #ifdef GARBAGE
- int *q,*r;
-
- if (p == (int *)0) return;
-
- q = p; /* head of list */
- while (p) {
- r = p;
- if (*--p > 0) {
- *p = -*p;
- }
- p = *(int **)r;
- }
- *(int **)r = free_list;
- free_list = q;
- #else
- return;
- #endif
- }
-
- int expn(float fvalue) /*;expn*/
- {
- /* this procedure is supposed to return the exponent of a normalized
- * positive floating point number. Since it is supposed to be
- * rewritten as an host function, we didn't try to optimize it.
- */
-
- int exponent = 0;
-
- while(fvalue < 0.5) {
- fvalue *= 2.0;
- exponent -= 1;
- }
- while(fvalue >= 1.0) {
- fvalue /= 2.0;
- exponent += 1;
- }
- return exponent;
- }
-
- void check_subtype_with_discr(int *type_ptr, int discr_list[])
- /*;check_subtype_with_discr*/
- {
- int new_discr_list[MAX_DISCR];
- int *base_type_ptr, *discr_ptr, nb_discr, i, *component_ptr, nb_dim;
- int low, high;
- int nb_field, nb_fixed, *field_ptr, *case_table_ptr, *field_table_ptr;
- int first_field, last_field, next_case, *case_ptr;
- int discr_number, value_discr, nb_choices;
- int *type_ptr1, bas1, off1, *ptr1, *type_discr;
-
- if (TYPE(type_ptr) == TT_D_RECORD) {
- base_type_ptr = ADDR(D_TYPE(type_ptr)->dbase, D_TYPE(type_ptr)->doff);
- discr_ptr = type_ptr + WORDS_D_TYPE;
- nb_discr = D_TYPE(type_ptr)->nb_discr_d;
- field_ptr = base_type_ptr + WORDS_U_RECORD;
- for (i = 0; i < nb_discr; i++) {
- new_discr_list[i] = get_variable_bound(discr_ptr, discr_list);
- type_discr = ADDR (*(field_ptr+1), *(field_ptr+2));
- if ( I_RANGE(type_discr)->ilow > new_discr_list [i]
- || I_RANGE(type_discr)->ihigh < new_discr_list [i]) {
- raise (CONSTRAINT_ERROR, "Discr. does not hold in bounds");
- }
- field_ptr += 3;
- discr_ptr += 2;
- }
- check_subtype_with_discr(base_type_ptr, new_discr_list);
-
- }
-
- else if (TYPE(type_ptr) == TT_D_ARRAY) {
- base_type_ptr = ADDR(D_TYPE(type_ptr)->dbase, D_TYPE(type_ptr)->doff);
- discr_ptr = type_ptr + WORDS_D_TYPE;
- nb_dim = D_TYPE(type_ptr)->nb_discr_d;
-
- if ( TYPE(base_type_ptr) == TT_U_ARRAY
- || TYPE(base_type_ptr) == TT_C_ARRAY) {
- component_ptr =
- ADDR(ARRAY(base_type_ptr)->component_base,
- ARRAY(base_type_ptr)->component_offset);
- check_subtype_with_discr(component_ptr, NULL_INT);
- }
- else if (TYPE (base_type_ptr) == TT_S_ARRAY) {
- /* in a simple array, the component can only be a simple
- * type : therefore there is no need to test
- */
- return;
- }
-
- type_ptr1 = &(ARRAY(base_type_ptr)->index1_base);
- for (i = 1; i <= nb_dim; i++) {
- low = get_variable_bound(discr_ptr, discr_list);
- discr_ptr += 2;
- high = get_variable_bound(discr_ptr, discr_list);
- discr_ptr += 2;
-
- bas1 = *type_ptr1++;
- off1 = *type_ptr1++;
- ptr1 = ADDR(bas1, off1);
- if ((low <= high) && (I_RANGE(ptr1)->ilow > low
- || I_RANGE(ptr1)->ihigh < high)) {
- raise (CONSTRAINT_ERROR,
- "Array with discr. does not hold in bounds");
- }
- }
- }
- else if (TYPE(type_ptr) == TT_C_RECORD) {
- base_type_ptr = ADDR(C_RECORD(type_ptr)->cbase,
- C_RECORD(type_ptr)->coff);
- nb_discr = C_RECORD(type_ptr)->nb_discr_c;
- field_ptr = base_type_ptr + WORDS_U_RECORD;
- for (i = 0; i < nb_discr; i++) {
- new_discr_list[i] = *(type_ptr + WORDS_C_RECORD + i);
- type_discr = ADDR (*(field_ptr+1), *(field_ptr+2));
- if ( I_RANGE(type_discr)->ilow > new_discr_list [i]
- || I_RANGE(type_discr)->ihigh < new_discr_list [i]) {
- raise (CONSTRAINT_ERROR, "Discr. does not hold in bounds");
- }
- field_ptr += 3;
- }
- check_subtype_with_discr(base_type_ptr, new_discr_list);
- }
-
- else if (TYPE(type_ptr) == TT_V_RECORD) {
- nb_field = U_RECORD(type_ptr)->nb_field_u;
- nb_fixed = U_RECORD(type_ptr)->nb_fixed_u;
- field_table_ptr = type_ptr + WORDS_U_RECORD;
- case_table_ptr = field_table_ptr + 3 * nb_field;
- first_field = 0;
- last_field = nb_fixed - 1;
- next_case = U_RECORD(type_ptr)->first_case;
- for (;;) {
- field_ptr = 3 * first_field + field_table_ptr;
- for (i = first_field; i <= last_field; i++) {
- component_ptr = ADDR(*(field_ptr + 1), *(field_ptr + 2));
- check_subtype_with_discr(component_ptr, discr_list);
- field_ptr += 3;
- }
-
- if (next_case == -1)
- break;
-
- /* we have : next_case != -1 */
-
- case_ptr = case_table_ptr + next_case;
- discr_number = *case_ptr++;
- value_discr = discr_list[discr_number];
- nb_choices = *case_ptr;
- case_ptr += 4;
- val_high = *case_ptr;
- for (i = 2; i <= nb_choices; i++) {
- if (val_high > value_discr)
- break;
- case_ptr += 4;
- val_high = *case_ptr;
- }
- next_case = *--case_ptr;
- last_field = *--case_ptr;
- first_field = *--case_ptr;
- }
- }
- }
-